

import java.util.Random;

import javax.swing.JLabel;


/**Class MonteCarlo qui comprend les 2 méthodes la single et la multithreade
 * */
public class MonteCarloSingleThread implements Runnable {
	String callPutFlag;
	double s;
	double x;
	double t;
	double r;
	double b;
	double v;
	int nSteps;
	int nSimulations;
	
	private MonteCarloApp viewToUpdate;
	private Variables var;
	private JLabel label;
	private String setNb;
	
	public final String TYPE = "Singlethread";
	
	/**
	 * Constructor
	 * @param viewToUpdate
	 */
	public MonteCarloSingleThread (MonteCarloApp viewToUpdate) 
	{
		this.viewToUpdate = viewToUpdate;
	}
	
	/**
	 * Constructor
	 * @param a
	 * @param var
	 */
	public MonteCarloSingleThread (MonteCarloApp a, Variables var) {
		this(a); // to call the first constructor
		this.var = var;
	}
	
	/**
	 * Constructor
	 * @param a
	 * @param var
	 * @param label
	 */
	public MonteCarloSingleThread (MonteCarloApp a, Variables var, String setNb, JLabel label) {
		this(a);
		this.var = var;
		this.label = label;
		this.setNb = setNb;
	}

	/**
	 * Méthode qui lance le MonteCarlo en single thread, la méthode récupère les parametres nécessaires à l'appel
	 * @param var
	 * @return
	 */
	public double monteCarloStandardOption (Variables var)
	{
		callPutFlag=var.getCallputFlag();
		s = var.getS();
		x = var.getX();
		t = var.getT();
		r = var.getR();
		b = var.getB();
		v = var.getV();
		nSteps = var.getnSteps();
		nSimulations = var.getnSimulations();
		
		double dt;
		double st;
		double drift;
		double vSqrDt;
		double estim = 0;
		double sum = 0;
		int i;
		int j;
		int z = 0;

		Random random = new Random();
		
		long time_start = System.currentTimeMillis();

		dt = t/nSteps;
		drift = (b - (v*v) / 2)*dt;
		vSqrDt = v*Math.sqrt(dt);

		if(callPutFlag.equals("c"))
			z = 1;

		else if (callPutFlag.equals("p"))
			z = -1;

		for(i=1; i<=nSimulations; i++)
		{
			st = s;

			for(j=1; j<=nSteps; j++)
			{
				st = st * Math.exp( drift + vSqrDt * random.nextGaussian() );
			}

			sum = sum + Math.max(z * (st - x), 0);
			viewToUpdate.displayIntermediateValue(TYPE, sum/i, this.setNb, this.label);
		}

		estim = Math.exp(-r * t)*(sum/nSimulations);
		
		// To calculate the time of execution of the 
		long time_end = System.currentTimeMillis();
		long time_exec = time_end - time_start;	
		
		viewToUpdate.displayFinalValue(TYPE, estim, time_exec, this.setNb, this.label);
		return estim;
	}
	
	public JLabel getLabel() {
		return this.label;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		monteCarloStandardOption(var);
	}

}